#ifndef __CC_TCP_H__
#define __CC_TCP_H__

#include <stdint.h>

struct tcphdr
{
    uint16_t source;
    uint16_t dest;
    uint32_t seq;
    uint32_t ack_seq;
#ifdef __CC_BIG_ENDIAN
    uint16_t   doff:4,
               res1:4,
               cwr:1,
               ece:1,
               urg:1,
               ack:1,
               psh:1,
               rst:1,
               syn:1,
               fin:1;
#else
    uint16_t   res1:4,
               doff:4,
               fin:1,
               syn:1,
               rst:1,
               psh:1,
               ack:1,
               urg:1,
               ece:1,
               cwr:1;
#endif
    uint16_t window;
    uint16_t check;
    uint16_t urg_ptr;
};

#define TCPHDR_LEN 20

struct pseudoheader
{
    uint32_t sip;       // IP addr
    uint32_t dip;       // IP addr
    uint8_t  zero;      // checksum placeholder
    uint8_t  protocol;  // protocol number
    uint16_t len;       // packet length
};

static uint16_t in_chksum_tcp(uint16_t *h, uint16_t * d, int dlen)
{
    uint32_t cksum;
    uint16_t answer=0;

    // PseudoHeader must have 12 bytes
    cksum  = h[0];
    cksum += h[1];
    cksum += h[2];
    cksum += h[3];
    cksum += h[4];
    cksum += h[5];

    // TCP hdr must have 20 hdr bytes
    cksum += d[0];
    cksum += d[1];
    cksum += d[2];
    cksum += d[3];
    cksum += d[4];
    cksum += d[5];
    cksum += d[6];
    cksum += d[7];
    cksum += d[8];
    cksum += d[9];

    dlen  -= 20; // bytes
    d     += 10; // short's

    while(dlen >=32)
    {
        cksum += d[0];
        cksum += d[1];
        cksum += d[2];
        cksum += d[3];
        cksum += d[4];
        cksum += d[5];
        cksum += d[6];
        cksum += d[7];
        cksum += d[8];
        cksum += d[9];
        cksum += d[10];
        cksum += d[11];
        cksum += d[12];
        cksum += d[13];
        cksum += d[14];
        cksum += d[15];
        d     += 16;
        dlen  -= 32;
    }

    while(dlen >=8)
    {
        cksum += d[0];
        cksum += d[1];
        cksum += d[2];
        cksum += d[3];
        d     += 4;
        dlen  -= 8;
    }

    while(dlen > 1)
    {
        cksum += *d++;
        dlen  -= 2;
    }

    if(dlen == 1)
    {
        // printf("new checksum odd byte-packet\n");
        *(uint8_t*)(&answer) = (*(uint8_t*)d);
        cksum += answer;
    }

    cksum  = (cksum >> 16) + (cksum & 0x0000ffff);
    cksum += (cksum >> 16);

    return (uint16_t)(~cksum);
}


#endif

